/**
 * Copyright(c) 2013 Jade Techonologies Co., Ltd.
 *
 * History:
 *   13-4-28 下午3:05 Created by dwzhang
 */
package com.jade.framework.startup;

import java.io.File;

import com.jade.framework.base.JadeSystem;
import com.jade.framework.base.text.VariableUtils;
import com.jade.framework.startup.def.ConfigDefinition;
import com.jade.framework.startup.def.HostDefinition;
import com.jade.framework.startup.def.ServerDefinition;
import com.jade.framework.startup.def.SystemDefinition;
import org.apache.commons.digester3.Digester;
import org.apache.commons.digester3.Rule;
import org.apache.commons.digester3.Substitutor;
import org.apache.commons.digester3.substitution.VariableExpander;
import org.apache.commons.digester3.substitution.VariableSubstitutor;
import org.apache.commons.lang3.StringUtils;
import org.xml.sax.Attributes;

/**
 * 抽象的部署器。
 *
 * @author dwzhang
 * @version 1.0 13-4-28 下午3:05
 */
public abstract class AbstractServerDeployer implements ServerDeployer
{
    public void loadSystemMeta(String xml)
    {
        // allow expansion in both xml attributes and element text
        Substitutor substitutor = new VariableSubstitutor(new JadeVariableExpander());
        Digester digester = new Digester();
        digester.setSubstitutor(substitutor);
        try {
            digester.addRule("system/config/property", new PropertyRule());

            digester.push(SystemDefinition.getInstance());
            //digester.addObjectCreate("system", SystemDefinition.class);
            digester.addObjectCreate("system/servers/server", ServerDefinition.class);
            digester.addSetProperties("system/servers/server");
            digester.addObjectCreate("system/servers/server/config", ConfigDefinition.class);
            digester.addSetProperties("system/servers/server/config");
            digester.addSetNext("system/servers/server/config", "addConfig");
            digester.addSetNext("system/servers/server", "addServer");
            digester.addObjectCreate("system/hosts/host", HostDefinition.class);
            digester.addSetProperties("system/hosts/host");
            digester.addCallMethod("system/hosts/host/server", "addServer", 1);
            digester.addCallParam("system/hosts/host/server", 0, "type");
            digester.addSetNext("system/hosts/host", "addHost");
            digester.setValidating(false);
            digester.parse(new File(xml));
        }
        catch (Throwable t) {
            JadeSystem.getLog().error("Can't parse xml " + xml, t);
        }
    }

    protected class JadeVariableExpander implements VariableExpander
    {
        public String expand(String s)
        {
            return VariableUtils.evaluate(s, null);
        }
    }

    protected class PropertyRule extends Rule
    {
        @Override
        public void begin(String namespace, String name, Attributes attributes)
                throws Exception
        {
            String key = attributes.getValue("name");
            String value = attributes.getValue("value");
            JadeSystem.setProperty(key, replaceValue(value));
        }
    }

    public String replaceValue(String value)
    {
        if (StringUtils.isBlank(value)) {
            return value;
        }

        String real = value;
        if (value.startsWith("{") && value.endsWith("}")) {
            String key = value.substring(1, value.length() - 1);
            real = JadeSystem.getProperty(key, value);
        }
        return real;
    }
}
